package project

import (
	"context"
	"encoding/json"
	"fmt"
	"gf-assistant/internal/common/factory"
	"gf-assistant/internal/project/parameter"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"reflect"
)

type TaskDao struct{}

func init() {
	taskDao := TaskDao{}
	factory.Put(reflect.TypeOf(taskDao).String(), &taskDao)
}
func (dao *TaskDao) DB() gdb.DB {
	return g.DB()
}
func (dao *TaskDao) ListTask(ctx context.Context, req *parameter.ListTaskReq) (tasks []*parameter.GetTaskRes) {
	parameters := make([]interface{}, 0)
	sql := `
		  	SELECT T.TASK_ID AS TaskId,T.PROJECT_ID AS ProjectId,T.PARENT_ID AS ParentId,T.TASK_NAME AS TaskName,
						 T.TASK_CODE AS TaskCode,DATE_FORMAT(T.START_DATE,'%Y-%m-%d') AS StartDate,DATE_FORMAT(T.END_DATE,'%Y-%m-%d') AS EndDate,
						 T.TASK_STATUS AS TaskStatus, ELT(FIELD(t.TASK_STATUS, 1, 2,3,4),'待分配','已分配','进行中','已完成')AS TaskStatusName,
						 T.MEMBER_ID AS MemberId,PM.NICK_NAME AS MemberName, T.REMARK AS Remark
			FROM PROJECT_TASK T  
			LEFT JOIN PROJECT_MEMBER M ON M.MEMBER_ID=T.MEMBER_ID
			LEFT JOIN SYS_USER PM ON PM.USER_ID=M.USER_ID
		  	where t.PROJECT_ID=?
		  		and T.ENABLE_STATUS=1
		  `
	parameters = append(parameters, req.ProjectId) //项目Id
	sql = sql + " ORDER BY T.PARENT_ID, T.START_DATE \n"
	resultList, err := g.DB().GetAll(ctx, sql, parameters)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	//遍历结构体切片
	for _, v := range resultList {
		task := parameter.GetTaskRes{}
		err = json.Unmarshal([]byte(v.Json()), &task)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
		}
		tasks = append(tasks, &task)
	}
	return tasks
}
func (dao *TaskDao) CreateTask(tx gdb.TX, req *parameter.CreateTaskReq) (res *parameter.CreateTaskRes, err error) {
	sql := `
			insert into PROJECT_TASK(PROJECT_ID,PARENT_ID,TASK_NAME,TASK_CODE,
			                         START_DATE,END_DATE,
			                         REMARK,ENABLE_STATUS,TASK_STATUS,
			                         CREATE_TIME,CREATE_USER,UPDATE_TIME,UPDATE_USER)
			values (?,?,?,?,?,?,?,1,1,now(),?,now(),?)
			on duplicate key update
			UPDATE_TIME=now()                     
		  `
	parameters := make([]interface{}, 0)
	parameters = append(parameters, req.ProjectId, req.ParentId, req.TaskName, req.TaskCode,
		req.StartDate, req.EndDate, req.Remark, req.GetOperatorId(), req.GetOperatorId())

	result, err := tx.Exec(sql, parameters)
	if err != nil {
		fmt.Printf("insert task faied, error:[%v]", err.Error())
		return nil, err
	}
	_, err = result.LastInsertId()
	return &parameter.CreateTaskRes{}, err
}
func (dao *TaskDao) SaveTask(tx gdb.TX, req *parameter.SaveTaskReq) {
	sql := `
			update PROJECT_TASK set
				TASK_NAME=?,
				TASK_CODE=?,
			    START_DATE=?,
			    END_DATE=?,
			    REMARK=?,
			    UPDATE_TIME=now(),
			    UPDATE_USER=?
			where TASK_ID=?
		  `
	parameters := make([]interface{}, 0)
	parameters = append(parameters, req.TaskName, req.TaskCode,
		req.StartDate, req.EndDate, req.Remark, req.GetOperatorId(), req.TaskId)

	_, err := tx.Exec(sql, parameters)
	if err != nil {
		fmt.Printf("insert task faied, error:[%v]", err.Error())
		panic("500#修改任务失败")
	}
}
func (dao *TaskDao) DeleteTask(tx gdb.TX, req *parameter.DeleteTaskReq) {
	sql := `
			update PROJECT_TASK set
			    ENABLE_STATUS=0,
			    UPDATE_TIME=now(),
			    UPDATE_USER=?
			where TASK_ID=?
		  `
	parameters := make([]interface{}, 0)
	parameters = append(parameters, req.GetOperatorId(), req.TaskId)

	_, err := tx.Exec(sql, parameters)
	if err != nil {
		fmt.Printf("insert task faied, error:[%v]", err.Error())
		panic("500#删除任务失败")
	}
}
func (dao *TaskDao) DistributeTask(tx gdb.TX, req *parameter.DistributeTaskReq) {
	sql := `
			update PROJECT_TASK set
				MEMBER_ID=?,
				TASK_STATUS=2,
			    START_DATE=?,
			    END_DATE=?,
			    UPDATE_TIME=now(),
			    UPDATE_USER=?
			where TASK_ID=?
		  `
	_, err := tx.Exec(sql, req.MemberId, req.StartDate, req.EndDate, req.GetOperatorId(), req.TaskId)
	if err != nil {
		fmt.Printf("update task faied, error:[%v]", err.Error())
		panic("500#分配任务失败")
	}
	sql = `
			insert into PROJECT_TASK_RECORD(TASK_ID, RECORD_EVENT, USER_ID, CREATE_TIME,CREATE_USER) 
			values (?,1,(select USER_ID from PROJECT_MEMBER where MEMBER_ID=?),now(),?)
		  `
	_, err = tx.Exec(sql, req.TaskId, req.MemberId, req.GetOperatorId())
	if err != nil {
		fmt.Printf("insert task faied, error:[%v]", err.Error())
		panic("500#分配任务失败")
	}
}
func (dao *TaskDao) GetTimeLineTask(ctx context.Context, req *parameter.GetTaskTimeLineReq) (timeLines []*parameter.TaskTimeLineRes) {
	sql := `
		  	SELECT T.CREATE_TIME AS Title,concat(C.NICK_NAME,ELT(FIELD(t.RECORD_EVENT, 1, 2,3),'分配任务','开始任务','关闭任务'),'.',IFNULL(M.NICK_NAME,'')) as Content
			FROM PROJECT_TASK_RECORD T  
			LEFT JOIN SYS_USER C ON C.USER_ID=T.CREATE_USER
			LEFT JOIN SYS_USER M ON M.USER_ID=T.USER_ID
		  	where T.TASK_ID=?
		  `
	sql = sql + " ORDER BY T.CREATE_TIME DESC \n"
	resultList, err := g.DB().GetAll(ctx, sql, req.TaskId)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	//遍历结构体切片
	for _, v := range resultList {
		timeLine := parameter.TaskTimeLineRes{}
		err = json.Unmarshal([]byte(v.Json()), &timeLine)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
		}
		timeLines = append(timeLines, &timeLine)
	}
	return timeLines
}
func (dao *TaskDao) GetMyTask(ctx context.Context, req *parameter.MyTaskReq) (tasks []*parameter.GetTaskRes) {
	parameters := make([]interface{}, 0)
	sql := `
		with RECURSIVE T_TASK as (
			select t.*
			FROM PROJECT_TASK t 
			JOIN PROJECT_MEMBER m on t.MEMBER_ID=m.MEMBER_ID 
				and m.ENABLE_STATUS=1 
				and t.PROJECT_ID=m.PROJECT_ID 
				and m.USER_ID=?
			WHERE t.ENABLE_STATUS=1
			union all
			select t2.* 
			from PROJECT_TASK t2 join T_TASK t on t2.TASK_ID = t.PARENT_ID 
				and t.PROJECT_ID=t2.PROJECT_ID
			WHERE t2.ENABLE_STATUS=1
		) 
		select distinct T.TASK_ID AS TaskId,T.PROJECT_ID AS ProjectId,T.PARENT_ID AS ParentId,T.TASK_NAME AS TaskName,
			 T.TASK_CODE AS TaskCode,DATE_FORMAT(T.START_DATE,'%Y-%m-%d') AS StartDate,DATE_FORMAT(T.END_DATE,'%Y-%m-%d') AS EndDate,
			 T.TASK_STATUS AS TaskStatus, ELT(FIELD(t.TASK_STATUS, 1, 2,3,4),'待分配','已分配','进行中','已完成')AS TaskStatusName,
			 T.REMARK AS Remark 
		from T_TASK T 
		where T.PROJECT_ID=?
		  `
	parameters = append(parameters, req.GetUserId(), req.ProjectId) //项目Id
	sql = sql + " ORDER BY T.PARENT_ID, DATE_FORMAT(T.START_DATE,'%Y-%m-%d') \n"
	resultList, err := g.DB().GetAll(ctx, sql, parameters)
	if err != nil {
		fmt.Printf("query faied, error:[%v]", err.Error())
		return
	}
	//遍历结构体切片
	for _, v := range resultList {
		task := parameter.GetTaskRes{}
		err = json.Unmarshal([]byte(v.Json()), &task)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
		}
		tasks = append(tasks, &task)
	}
	return tasks
}
func (dao *TaskDao) BeginTask(tx gdb.TX, req *parameter.BeginTaskReq) {
	sql := `
			update PROJECT_TASK set
			    TASK_STATUS=3,
			    UPDATE_TIME=now(),
			    UPDATE_USER=?
			where TASK_ID=?
		  `
	_, err := tx.Exec(sql, req.GetUserId(), req.TaskId)
	if err != nil {
		fmt.Printf("update task faied, error:[%v]", err.Error())
		panic("500#修改任务失败")
	}
	sql = `
			insert into PROJECT_TASK_RECORD(TASK_ID,RECORD_EVENT,USER_ID,RECORD_DATE,CREATE_TIME,CREATE_USER)
			values(?,2,?,?,now(),?)
		  `
	_, err = tx.Exec(sql, req.TaskId, req.GetUserId(), req.StartDate, req.GetUserId())
	if err != nil {
		fmt.Printf("insert task_record faied, error:[%v]", err.Error())
		panic("500#开始任务失败")
	}
}
func (dao *TaskDao) DoneTask(tx gdb.TX, req *parameter.DoneTaskReq) {
	sql := `
			update PROJECT_TASK set
			    TASK_STATUS=4,
			    UPDATE_TIME=now(),
			    UPDATE_USER=?
			where TASK_ID=?
		  `
	_, err := tx.Exec(sql, req.GetUserId(), req.TaskId)
	if err != nil {
		fmt.Printf("update task faied, error:[%v]", err.Error())
		panic("500#修改任务失败")
	}
	sql = `
			insert into PROJECT_TASK_RECORD(TASK_ID,RECORD_EVENT,USER_ID,RECORD_DATE,CREATE_TIME,CREATE_USER)
			values(?,3,?,?,now(),?)
		  `
	_, err = tx.Exec(sql, req.TaskId, req.GetUserId(), req.EndDate, req.GetUserId())
	if err != nil {
		fmt.Printf("insert task_record faied, error:[%v]", err.Error())
		panic("500#开始任务失败")
	}
}
